/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utilidades;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author wiland
 */
public class CrearTablasBD {

    private ArrayList<String> pks;
    private PrintWriter wr;
    private BufferedWriter bw;
    private String packageCrud;
    private String packageClases;
    private String packageAnotaciones;
    private String carpetaClases;
    private String ruta;

    public CrearTablasBD() {
        generarPaquetes();
        obtenerTablasBD();
    }

    private void obtenerTablasBD() {
        Conexion con;
        Connection c = null;
        ResultSet rs = null, rsCampos = null;
        StringBuilder sbAtr, sbMet;
        Boolean b = false;
        String tabla;

        try {
            con = new Conexion();
            c = con.getConexion();
            DatabaseMetaData metaData = c.getMetaData();
            ResultSetMetaData rsmd;
            Statement st;

            rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
            ruta = "src/" + this.packageClases.replaceAll("\\.", "/") + "/";
            this.crearPaquete(ruta);

            while (rs.next()) {
                sbAtr = new StringBuilder();
                sbMet = new StringBuilder();
                tabla = rs.getString(3);
                this.abrirStream(ruta + tabla + ".java");
                sbAtr.append("package " + this.packageClases + ";\n\n");
                sbAtr.append("import " + this.packageCrud + ".Crud;\n");
                sbAtr.append("import " + this.packageAnotaciones + ".Columna;\n\n");
                sbAtr.append("public class " + tabla + " extends Crud {\n");

                crearMetaDataPK(metaData.getPrimaryKeys(null, null, tabla));
                st = c.createStatement();
                rsCampos = st.executeQuery("select * from " + tabla + " limit 1");
                rsmd = rsCampos.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    sbAtr.append("    @Columna");
                    if (rsmd.isAutoIncrement(i) || isPK(rsmd.getColumnName(i))) {
                        sbAtr.append("(");
                        if (isPK(rsmd.getColumnName(i))) {
                            sbAtr.append("PK = true");
                            b = true;
                        }

                        if (rsmd.isAutoIncrement(i)) {
                            sbAtr.append(b ? ", " : "");
                            sbAtr.append("AI = true");
                        }

                        sbAtr.append(")");
                    }
                    sbAtr.append("\n");
                    sbAtr.append("    private " + rsmd.getColumnClassName(i) + " " + rsmd.getColumnName(i) + ";\n");

                    String campo = rsmd.getColumnName(i).substring(0, 1).toUpperCase() + rsmd.getColumnName(i).substring(1);

                    sbMet.append("    public void set" + campo + "(" + rsmd.getColumnClassName(i) + " " + rsmd.getColumnName(i) + ") {\n");
                    sbMet.append("        this." + rsmd.getColumnName(i) + " = " + rsmd.getColumnName(i) + ";\n");
                    sbMet.append("    }\n\n");

                    sbMet.append("    public " + rsmd.getColumnClassName(i) + " get" + campo + "() {\n");
                    sbMet.append("        return this." + rsmd.getColumnName(i) + ";\n");
                    sbMet.append("    }\n\n");
                }
                this.escribir(sbAtr.toString());

                sbMet.append("    public " + tabla + "() {\n\n");
                sbMet.append("    }\n");
                sbMet.append("}");

                this.escribir(sbMet.toString());
                this.cerrarStream(ruta);
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                rs.close();
                rsCampos.close();
                c.close();
            } catch (Exception e) {
            }
        }
    }

    public void crearMetaDataPK(ResultSet rs) {
        pks = new ArrayList();
        try {
            while (rs.next()) {
                pks.add(rs.getString(4));
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public boolean isPK(String col) {
        for (String columna : pks) {
            if (columna.equalsIgnoreCase(col)) {
                return true;
            }
        }
        return false;
    }

    private void crearPaquete(String ruta) {
        File f;
        f = new File(ruta);
        try {
            f.mkdirs();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void abrirStream(String ruta) {
        File f;
        f = new File(ruta);
        if (f.exists()) {
            f.delete();
        }

        try {
            f.createNewFile();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        try {
            FileWriter w = new FileWriter(f);
            bw = new BufferedWriter(w);
            wr = new PrintWriter(bw);
        } catch (IOException e) {
        }
    }

    private void escribir(String val) {
        wr.write(val + "\n");//escribimos en el archivo
    }

    private void cerrarStream(String ruta) {
        try {
            wr.close();
            bw.close();
            System.out.println("Se ha creado el archivo en la ruta: " + ruta);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void generarPaquetes() {
        String paquete = this.getClass().getPackage().toString().substring(8).trim();
        if (paquete.lastIndexOf(".") != -1) {
            paquete = paquete.substring(0, paquete.lastIndexOf("."));
        }
        this.packageCrud = paquete + ".crud";
        this.packageClases = paquete + ".tablas";
        this.packageAnotaciones = paquete + ".anotaciones";
    }

    public String getCarpetaClases() {
        return carpetaClases;
    }

    public void setCarpetaClases(String carpetaClases) {
        this.carpetaClases = carpetaClases;
    }

    public static void main(String[] args) {
//        tbl_cib cib = new tbl_cib();
//        List<tbl_cib> list = (List<tbl_cib>)cib.select();
//        
//        for (tbl_cib p : list) {
//            System.out.println(p.getId_tbl_cib());
//        }
//        
//        
        
        new CrearTablasBD();
    }
}
